package cn.mw.cmdb.viewProcessor;

import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.param.ModelPropertyParam;
import cn.mw.cmdb.processor.ModelViewTypeContext;
import cn.mw.cmdb.processor.ModelViewTypeProccessor;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.service.impl.ModelPropertyServiceImpl;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.ModelInfo.prefix;
import static cn.mw.cmdb.entity.PropertyType.relationIdKey;
import static cn.mw.cmdb.entity.PropertyTypeEnumSingle.defaultValueKey;
import static cn.mw.cmdb.entity.PropertyTypeEnumSingle.enumInfoListKey;
import static cn.mw.cmdb.viewProcessor.ModelViewRoomProcess.getRoomPropertyIds;
import static cn.mw.cmdb.viewProcessor.ModelViewRoomProcess.layoutDataRoom;
import static cn.mw.cmdb.viewProcessor.ModelViewUNumProcess.getUNumTypePropertyIds;
import static cn.mw.components.mongodb.entity.MongoPropertyType.strValueConvert;

public class ModelViewCabinetProcess implements ModelViewTypeProccessor {
    public static String cabinetCode = prefix + "cabinetCode";
    private static String cabinetDesc = prefix + "cabinetDesc";
    public static String UNum = prefix + "UNum";
    public static String relationRoom =prefix +  "relationRoom";

    public static String relationRoomArea =prefix +  "relationRoomArea";
    public static String cabinetPosition =prefix +  "cabinetPosition";
    public static String layoutDataCabinet =prefix +  "layoutDataCabinet";

    private static String cabinetCodeKey = "编号";
    private static String cabinetDescKey = "描述";
    private static String UNumKey = "U位";
    public static String cabinetPositionKey = "机柜位置";
    public static String relationRoomKey = "上架机房";

    public static String relationRoomAreaKey = "上架区域";
    private static String layoutKey = "布局样式";
    private static String cabinetCatologName = "机柜布局";
    private static String layoutDataKey =prefix +  "layoutData";
    public static String cabinetRuleType = prefix + "cabinetRuleType";
    private static String cabinetRuleTypeKey = "占位规则";
    public static String cabinetRuleTypeUpKey = "向上占位";
    public static String cabinetRuleTypeDownKey = "向下占位";


    @Override
    public Object genModelViewProperty(ModelViewTypeContext context) throws Exception {
        if (context != null && context.getParam() != null && (context.getParam() instanceof ModelInfo)) {
            ModelInfo param = (ModelInfo) context.getParam();
            Map<String, PropertyInfo> properties = param.getProperties();
            CmdbServiceManage cmdbServiceManage = context.getCmdbServiceManage();
            ModelPropertyServiceImpl service = (ModelPropertyServiceImpl) cmdbServiceManage.getModelService(ModelPropertyServiceImpl.ID);
            //清除其他视图对应的字段
            ModelPropertyParam propertyParam = editorModelPropertyField(param);
            service.doRemove(propertyParam);

            //内置机柜模型字段，新增机柜模型时，自动生成
            PropertyInfo propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(cabinetCodeKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            PropertyTypeRef typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeString.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(cabinetCode);
            propertyInfo.setSortNum(1);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(cabinetDescKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeString.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(cabinetDesc);
            propertyInfo.setSortNum(2);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(relationRoomKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeExtSingle.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(relationRoom);
            propertyInfo.setSortNum(3);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(relationRoomAreaKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeExtSingle.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(relationRoomArea);
            propertyInfo.setSortNum(4);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(cabinetPositionKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeList.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(cabinetPosition);
            propertyInfo.setSortNum(4);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(cabinetRuleTypeKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(false);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeEnumSingle.ID);
            Map contextMap = new HashMap();
            contextMap.put(enumInfoListKey, Arrays.asList(cabinetRuleTypeUpKey, cabinetRuleTypeDownKey));
            contextMap.put(defaultValueKey, cabinetRuleTypeUpKey);
            typeRef.setContext(contextMap);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(cabinetRuleType);
            propertyInfo.setSortNum(5);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(UNumKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeInt.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(UNum);
            propertyInfo.setSortNum(6);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(layoutKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(cabinetCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeLayoutCabinet.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(layoutDataCabinet);
            propertyInfo.setSortNum(7);
            properties.put(propertyInfo.getId(), propertyInfo);

        }
        return null;
    }

    /**
     * 清除U位管理视图对应的字段
     */
    public static ModelPropertyParam editorModelPropertyField(ModelInfo param) {
        ModelPropertyParam propertyParam = new ModelPropertyParam();
        Set<String> ids = new HashSet<>();
        getRoomPropertyIds(ids);
        getUNumTypePropertyIds(ids);

        propertyParam.setIds(new ArrayList<>(ids));
        propertyParam.setModelId(param.getId());
        return propertyParam;
    }

    public static Set<String> getCabinetPropertyIds(Set<String> ids){
        ids.add(cabinetCode);
        ids.add(cabinetDesc);
        ids.add(relationRoom);
        ids.add(relationRoomArea);
        ids.add(cabinetPosition);
        ids.add(cabinetRuleType);
        ids.add(UNum);
        ids.add(layoutDataCabinet);
        return ids;
    }

    @Override
    public Object addInstanceHandle(ModelViewTypeContext context) throws Exception {
        //机柜新增时，需要同步机房的布局数据
        CmdbServiceManage cmdbServiceManage = context.getCmdbServiceManage();
        InstanceServiceImpl modelService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);

        List<InstanceInfo> instanceInfoList = (List<InstanceInfo>) context.getParam();
        //获取关联机房id对应的机柜实例数据
        Map<String, List<InstanceInfo>> cabinetInfosByRoomId = instanceInfoList.stream().filter(s -> s.getData() != null && s.getData().get(relationRoom) != null).collect(Collectors.groupingBy(s -> strValueConvert(((Map) s.getData().get(relationRoom)).get(relationIdKey))));
        //获取所有的关联机房Id
        Set<String> relationRoomId = instanceInfoList.stream().filter(s -> s.getData() != null && s.getData().get(relationRoom) != null).map(s -> strValueConvert(((Map) s.getData().get(relationRoom)).get(relationIdKey))).collect(Collectors.toSet());
        //根据机房id获取机房实例信息
        List<InstanceInfo> relationRoomInstanceInfos = modelService.doListByIdsNotAuth(new ArrayList<>(relationRoomId));
        //获取机房id和对应的机房布局数据
        Map<String, Object> layoutDataRoomById = relationRoomInstanceInfos.stream().filter(s -> s.getData() != null && s.getData().get(layoutDataRoom) != null).collect(Collectors.toMap(s -> s.getId(), s -> s.getData().get(layoutDataRoom), (o1, o2) -> o1));
        if (cabinetInfosByRoomId != null) {
            cabinetInfosByRoomId.forEach((k, v) -> {
                String roomId = k;
                List<InstanceInfo> cabinetInstances = v;

                if (layoutDataRoomById != null && layoutDataRoomById.containsKey(roomId)) {
                    //获取布局数据
                    Object layoutDataObj = layoutDataRoomById.get(roomId);
                    if (layoutDataObj != null && layoutDataObj instanceof Map) {
                        Map layoutDataMap = (Map) layoutDataObj;
                        Object layoutDataMapObj = layoutDataMap.get(layoutDataKey);
                        if (layoutDataMapObj != null && layoutDataMapObj instanceof List) {
                        }
                    }
                }
            });
        }


        return null;
    }

    @Override
    public Object updInstanceHandle(ModelViewTypeContext context) throws Exception {
        return null;
    }
}
